home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / vbcc / machines / amigappc / startup / startup.s < prev   
Encoding:
Text File  |  1998-06-24  |  10.2 KB  |  507 lines

  1. ##
  2. ## startup.s
  3. ##
  4. ## Startup code for PowerPC programs using the PowerUp kernel
  5. ## It saves registers, initializes _stdin, _stdout and _stderr,
  6. ## parses the command line and calls _main().
  7. ##
  8. ##
  9. ## V0.9 23-Dec-97 phx
  10. ##    No longer expect argc/argv from ppcrun/elfrun/etc.. A command
  11. ##    line pointer is received in r3 and must be parsed first. If no
  12. ##    problems occur, _main() will receive argc/argv as usual. Other-
  13. ##    wise it will get argc=argv=0.
  14. ##    Still no WB-startup support...
  15. ##    Fixed a bug with stderr (Enforcer-hit/IsInteractive()) in
  16. ##    "Non-StartupMessage mode".
  17. ##    Successfully tested with ppc.library V45.2.
  18. ## V0.8 21-Nov-97 phx
  19. ##    CallOS()-fix for ppc.library V44.29 with old libamiga.a.
  20. ## V0.7 02-Nov-97 phx
  21. ##    Shorter startup code by using stmw/lmw.
  22. ## V0.6 18-Oct-97 phx
  23. ##    The ppc.library executes ELF objects at .text+4, so the first
  24. ##    instruction was always skipped... :(
  25. ##    SysBase is exported. DOSBase must be initialized by _main().
  26. ## V0.5 15-Oct-97 phx
  27. ##    Also works with R.Schmidt's ppcload.
  28. ##    Supports blr in _main(), although libvc.a jumps to _exit directly.
  29. ##      No longer use r13 for debugging output. It's reserved for
  30. ##    Small Data pointer in V.4. :P
  31. ## V0.4 13-Oct-97 phx
  32. ##    No longer touches r2. r2 is reserved in System V.4 ABI!
  33. ## V0.3 07-Oct-97 phx
  34. ##    Rewritten in pure PowerPC assembler (pasm).
  35. ## V0.2 04-Oct-97 phx
  36. ##      Use "CONSOLE:" instead "*" (PowerPC will definitely not run
  37. ##      under Kickstart 1.x :)
  38. ##      argc and argv are passed via startup message. argc and argv are
  39. ##      also passed in GPR3 and GPR4 but I will better read them from the
  40. ##      startup message...
  41. ##      When the program terminates, the result code is returned in
  42. ##      the startup message, which is replied then.
  43. ## V0.1 03-Oct-97 phx
  44. ##      created
  45.  
  46.  
  47. .set    DEBUG,0        # set to 1 for serial debugging
  48. .set    WAITBUTTON,0    # if 1, then wait for left mouse button,
  49.             #  after debugging output
  50. .set    CALLOSFIX,1    # ppc.library V44.29 has PPCCallOS(), but
  51.             #  old libamiga.a stil uses CallOS().
  52.  
  53. # powerup includes
  54. .set    PPCTASKTAG_STARTUP_MSG,0x80020015
  55. .set    PPCTASKTAG_STARTUP_MSGDATA,0x80020016
  56.  
  57. # struct StartupData
  58. .set    sd_M68kPort,0    # the PowerPC task can send messages to this port
  59. .set    sd_std_in,4    # standard input handle
  60. .set    sd_std_out,8    # standard output handle
  61. .set    sd_std_err,12    # standard error handle
  62. .set    sd_retCode,16    # PPC return code, passed on to M68k
  63. .set    sd_flags,20    # additional flags (currently unused)
  64.  
  65. .set    IOERROR,50    # can't open stdin/stdout/stderr
  66.  
  67. # serial debugging
  68. .if    DEBUG
  69.     .extern    PPCRawDoFmt
  70.  
  71. .macro    _debug        # _debug <format string>[,<gpr>, ...]
  72.     .data        # ... works with all GPRs, except r12
  73. .db\@:    .string    \1
  74.     .text
  75.     stwu    r12,-4(r1)
  76.     lis    r12,.regsave@ha
  77.     addi    r12,r12,.regsave@l
  78.     stw    r0,0(r12)
  79.     stw    r3,4(r12)
  80.     stw    r4,8(r12)
  81.     stw    r5,12(r12)
  82.     stw    r6,16(r12)
  83.     stw    r7,20(r12)
  84.     stw    r8,24(r12)
  85.     stw    r9,28(r12)
  86.     stw    r10,32(r12)
  87.     stw    r11,36(r12)
  88.     lwz    r3,0(r1)
  89.     addi    r1,r1,4
  90.     stw    r3,40(r12)
  91.     lwz    r3,4(r12)
  92.     .ifge    $NARG-2
  93.     lis    r12,.datastream@ha
  94.     addi    r12,r12,.datastream@l
  95.     stw    \2,0(r12)
  96.     .endif
  97.     .ifge    $NARG-3
  98.     stw    \3,4(r12)
  99.     .endif
  100.     .ifge    $NARG-4
  101.     stw    \4,8(r12)
  102.     .endif
  103.     .ifge    $NARG-5
  104.     stw    \5,12(r12)
  105.     .endif
  106.     .iflt    $NARG-2
  107.     li    r4,0
  108.     .else
  109.     mr    r4,r12
  110.     .endif
  111.     lis    r3,(.db\@)@ha
  112.     addi    r3,r3,(.db\@)@l
  113.     li    r5,1
  114.     li    r6,0
  115.     bl    PPCRawDoFmt        # output to serial line
  116. .if    WAITBUTTON
  117.     lis    r12,0xbfe001@h        # wait for left mouse button
  118.     ori    r12,r12,0xbfe001@l
  119. .dbwait1\@:
  120.     lbz    r3,0(r12)
  121.     andi.    r3,r3,0x40
  122.     bne    .dbwait1\@
  123. .dbwait2\@:
  124.     lbz    r3,0(r12)
  125.     andi.    r3,r3,0x40
  126.     beq    .dbwait2\@
  127. .endif
  128.     lis    r12,.regsave@ha
  129.     addi    r12,r12,.regsave@l
  130.     lwz    r0,0(r12)
  131.     lwz    r3,4(r12)
  132.     lwz    r4,8(r12)
  133.     lwz    r5,12(r12)
  134.     lwz    r6,16(r12)
  135.     lwz    r7,20(r12)
  136.     lwz    r8,24(r12)
  137.     lwz    r9,28(r12)
  138.     lwz    r10,32(r12)
  139.     lwz    r11,36(r12)
  140.     lwz    r12,40(r12)
  141. .endm
  142.  
  143. .else
  144. .macro    _debug
  145. .endm
  146. .endif
  147.  
  148.  
  149.     .text
  150.  
  151.     .extern    _main
  152.     .extern    PPCGetTaskAttr
  153.     .extern    PPCOpen
  154.     .extern    PPCClose
  155.     .extern    PPCAllocVec
  156.     .extern    PPCFreeVec
  157.  
  158.  
  159. # This is the first function in a program. Execution starts here!
  160.  
  161. __start:
  162.     nop                # ppc.library bug fix
  163.     stwu    r1,-448(r1)
  164.     mflr    r11
  165.     stw    r11,452(r1)
  166.     stmw    r14,224(r1)        # save all non-volatile registers
  167.     stfd    f14,296(r1)
  168.     stfd    f15,304(r1)
  169.     stfd    f16,312(r1)
  170.     stfd    f17,320(r1)
  171.     stfd    f18,328(r1)
  172.     stfd    f19,336(r1)
  173.     stfd    f20,344(r1)
  174.     stfd    f21,352(r1)
  175.     stfd    f22,360(r1)
  176.     stfd    f23,368(r1)
  177.     stfd    f24,376(r1)
  178.     stfd    f25,384(r1)
  179.     stfd    f26,392(r1)
  180.     stfd    f27,400(r1)
  181.     stfd    f28,408(r1)
  182.     stfd    f29,416(r1)
  183.     stfd    f30,424(r1)
  184.     stfd    f31,432(r1)
  185.     _debug    "\n-------\nstartup\n-------\nstack = 0x%08lx\n",r1
  186.     lis    r11,_init_stk@ha    # save initial stack pointer
  187.     stw    r1,_init_stk@l(r11)
  188.  
  189.     li    r14,0            # r14: argc = 0
  190.     mr.    r15,r3            # r15: command line/argv
  191.     bnel    parse_args
  192.     lis    r16,.constring@ha    # r16 = "CONSOLE:"
  193.     addi    r16,r16,.constring@l
  194.  
  195. # initialize SysBase
  196.     li    r3,4
  197.     lwz    r0,0(r3)
  198.     lis    r3,SysBase@ha
  199.     stw    r0,SysBase@l(r3)
  200.  
  201. # evaluate startup message from M68k
  202.     lis    r3,PPCTASKTAG_STARTUP_MSG@h
  203.     ori    r3,r3,PPCTASKTAG_STARTUP_MSG@l
  204.     bl    PPCGetTaskAttr
  205.     _debug    "PPCTASKTAG_STARTUP_MSG = 0x%08lx\n",r3
  206.     cmpwi    r3,0
  207.     beq    .1
  208.     lis    r3,PPCTASKTAG_STARTUP_MSGDATA@h
  209.     ori    r3,r3,PPCTASKTAG_STARTUP_MSGDATA@l
  210.     bl    PPCGetTaskAttr
  211.     _debug    "PPCTASKTAG_STARTUP_MSGDATA = 0x%08lx\n",r3
  212.     lwz    r4,sd_std_in(r3)    # get _stdin
  213.     lis    r11,_stdin@ha
  214.     stw    r4,_stdin@l(r11)
  215.     lwz    r5,sd_std_out(r3)    # get _stdout
  216.     lis    r11,_stdout@ha
  217.     stw    r5,_stdout@l(r11)
  218.     lwz    r6,sd_std_err(r3)    # get _stderr
  219.     lis    r11,_stderr@ha
  220.     stw    r6,_stderr@l(r11)
  221.     lis    r11,_startup_data@ha
  222.     stw    r3,_startup_data@l(r11)
  223.     _debug    "stdin=0x%08lx stdout=0x%08lx stderr=0x%08lx\n",r4,r5,r6
  224.     b    .startup
  225.  
  226. # get _stdin, _stdout, _stderr
  227. .1:    li    r4,1005
  228.     mr    r3,r16
  229.     bl    PPCOpen            # PPCOpen("CONSOLE:",MODE_OLDFILE)
  230.     _debug    "PPCOpen(\"%s\",MODE_OLDFILE) = 0x%08lx\n",r16,r3
  231.     cmpwi    r3,0
  232.     beq    __exit
  233.     lis    r11,_stdin@ha
  234.     stw    r3,_stdin@l(r11)
  235.  
  236.     li    r4,1006
  237.     mr    r3,r16
  238.     bl    PPCOpen            # PPCOpen("CONSOLE:",MODE_NEWFILE)
  239.     _debug    "PPCOpen(\"%s\",MODE_NEWFILE) = 0x%08lx\n",r16,r3
  240.     cmpwi    r3,0
  241.     beq    __exit
  242.     lis    r11,_stdout@ha
  243.     stw    r3,_stdout@l(r11)
  244.     lis    r12,_stderr@ha
  245.     stw    r3,_stderr@l(r12)    # _stderr = _stdout
  246.  
  247. # call _main in libvc.a
  248. .startup:
  249.     mr    r3,r14
  250.     mr    r4,r15
  251.     _debug    "calling _main(argc=%ld,argv=0x%08lx)\n",r3,r4
  252.     bl    _main            # _main(argc,argv)
  253.     li    r3,0
  254.     b    _exit
  255.  
  256.     .type    __start,@function
  257.     .size    __start,$-__start
  258.  
  259. .constring:
  260.     .string    "CONSOLE:"
  261.     .align    2
  262.  
  263.  
  264. __exit:
  265.     li    r3,IOERROR        # error: can't open stdin/stdout
  266.  
  267.  
  268.     .global    _exit
  269. _exit:
  270. # r3 = return code
  271.     mr    r14,r3
  272.     _debug    "\n-----\n_exit\n-----\nstack = 0x%08lx\nrc = %ld\n",r1,r14
  273. # free argv
  274.     lis    r11,_argv@ha
  275.     lwz    r3,_argv@l(r11)
  276.     bl    PPCFreeVec
  277.  
  278.     lis    r15,_startup_data@ha
  279.     lwz    r15,_startup_data@l(r15)
  280.     cmpwi    r15,0            # did we receive a startup message?
  281.     bne    .3
  282.  
  283. # close _stdout
  284.     lis    r11,_stdout@ha
  285.     lwz    r3,_stdout@l(r11)
  286.     cmpwi    r3,0
  287.     beq    .2
  288.     _debug    "PPCClose(stdout=0x%08lx)\n",r3
  289.     bl    PPCClose
  290.  
  291. # close _stdin
  292. .2:    lis    r11,_stdin@ha
  293.     lwz    r3,_stdin@l(r11)
  294.     cmpwi    r3,0
  295.     beq    .4
  296.     _debug    "PPCClose(stdin=0x%08lx)\n",r3
  297.     bl    PPCClose
  298.     b    .4
  299.  
  300. # write return code to startup message
  301. .3:    _debug    "store rc=%ld in startup data (0x%08lx)\n",r14,r15
  302.     stw    r14,sd_retCode(r15)
  303.  
  304. # restore initial stack frame
  305. .4:    mr    r3,r14
  306.     lis    r11,_init_stk@ha
  307.     lwz    r1,_init_stk@l(r11)
  308.     lmw    r14,224(r1)
  309.     lfd    f14,296(r1)
  310.     lfd    f15,304(r1)
  311.     lfd    f16,312(r1)
  312.     lfd    f17,320(r1)
  313.     lfd    f18,328(r1)
  314.     lfd    f19,336(r1)
  315.     lfd    f20,344(r1)
  316.     lfd    f21,352(r1)
  317.     lfd    f22,360(r1)
  318.     lfd    f23,368(r1)
  319.     lfd    f24,376(r1)
  320.     lfd    f25,384(r1)
  321.     lfd    f26,392(r1)
  322.     lfd    f27,400(r1)
  323.     lfd    f28,408(r1)
  324.     lfd    f29,416(r1)
  325.     lfd    f30,424(r1)
  326.     lfd    f31,432(r1)
  327.     lwz    r11,452(r1)
  328.     mtlr    r11
  329.     addi    r1,r1,448
  330.     blr
  331.  
  332.     .type    _exit,@function
  333.     .size    _exit,$-__exit
  334.  
  335.  
  336. .if    CALLOSFIX
  337.     .extern    PPCCallOS
  338.     .global    CallOS
  339. CallOS:
  340.     b    PPCCallOS
  341.  
  342.     .type    CallOS,@function
  343.     .size    CallOS,$-CallOS
  344. .endif
  345.  
  346.  
  347. parse_args:
  348. # Parse command line and generate argc/argv.
  349. # r14: argc=0
  350. # r15: cmdline (0-terminated, includes program name), will become argv
  351.     mflr    r11
  352.     mr    r10,r15
  353.     li    r12,0
  354. .pa1:    bl    nextarg
  355.     cmpwi    r3,0
  356.     beq    .pa2
  357.     addi    r12,r12,4        # another argv slot
  358.     bl    skiparg
  359.     cmpwi    r3,0
  360.     bne    .pa1
  361. .pa2:    cmpwi    r12,0
  362.     beq    .pa_nomem        # no arguments found?
  363.     addi    r12,r12,4        # + one termination slot
  364.     sub    r3,r10,r15
  365.     add    r3,r3,r12
  366.     li    r4,0            # MEMF_ANY
  367.     bl    PPCAllocVec        # memory for argv slots and buffer
  368.     mr    r10,r15
  369.     mr.    r15,r3
  370.     beq    .pa_nomem
  371.     lis    r9,_argv@ha
  372.     stw    r15,_argv@l(r9)
  373.     subi    r9,r15,4        # r9 argv slots
  374.     add    r12,r15,r12        # r12 argv buffer
  375. .pa4:    bl    nextarg
  376.     cmpwi    r3,0
  377.     beq    .pa_quit
  378.     stwu    r12,4(r9)        # store arg-pointer
  379.     addi    r14,r14,1        # increment argc
  380.     cmpwi    r3,0x22
  381.     bne    .pa10            # quoted?
  382. .pa5:    lbzu    r3,1(r10)
  383.     cmpwi    r3,0x22
  384.     bne    .pa6
  385.     addi    r10,r10,1        # end quote
  386.     li    r3,0
  387. .pa6:    cmpwi    r3,'*'            # BCPL escape character?
  388.     bne    .pa8
  389.     lbzu    r3,1(r10)
  390.     andi.    r4,r3,0xdf
  391.     cmpwi    r4,'N'            # newline
  392.     bne    .pa7
  393.     li    r3,10
  394. .pa7:    cmpwi    r4,'E'            # escape
  395.     bne    .pa8
  396.     li    r3,27
  397. .pa8:    stb    r3,0(r12)
  398.     addi    r12,r12,1
  399.     cmpwi    r3,0
  400.     bne    .pa5
  401.     b    .pa4
  402. .pa10:    stb    r3,0(r12)        # normal arg copy
  403.     addi    r12,r12,1
  404.     lbzu    r3,1(r10)
  405.     cmplwi    r3,0x20
  406.     bgt    .pa10
  407.     li    r3,0
  408.     b    .pa8
  409.  
  410. .pa_nomem:
  411.     li    r15,0
  412.     mtlr    r11
  413.     blr
  414. .pa_quit:
  415.     stwu    r3,4(r9)        # r3=0 terminates the arguments
  416.     mtlr    r11
  417.     blr
  418.  
  419.     .type    parse_args,@function
  420.     .size    parse_args,$-parse_args
  421.  
  422.  
  423. nextarg:
  424. # move pointer to beginning of next argument
  425. # r10: cmdline-pointer
  426. # -> r10: new cmdline-pointer, r3: char
  427.     lbz    r3,0(r10)
  428.     cmplwi    r3,0x20
  429.     bgtlr
  430.     cmpwi    r3,0
  431.     beqlr
  432.     addi    r10,r10,1
  433.     b    nextarg
  434.  
  435.     .type    nextarg,@function
  436.     .size    nextarg,$-nextarg
  437.  
  438.  
  439. skiparg:
  440. # move pointer behind the current argument
  441. # r10: cmdline-pointer
  442. # -> r10: new cmdline-pointer, r3: char
  443.     lbz    r3,0(r10)
  444.     cmpwi    r3,0x22            # " ?
  445.     beq    .skipquote
  446. .sk1:    cmplwi    r3,0x20
  447.     blelr
  448.     cmpwi    r3,0
  449.     beqlr
  450.     lbzu    r3,1(r10)
  451.     b    .sk1
  452. .skipquote:
  453.     lbzu    r3,1(r10)
  454.     cmpwi    r3,0
  455.     beqlr
  456.     cmpwi    r3,'*'            # escape?
  457.     bne    .sk2
  458.     lbzu    r4,1(r10)
  459.     cmpwi    r4,0
  460.     beqlr
  461. .sk2:    cmpwi    r3,0x22            # " ?
  462.     bne    .skipquote
  463.     lbzu    r3,1(r10)
  464.     blr
  465.  
  466.     .type    skiparg,@function
  467.     .size    skiparg,$-skiparg
  468.  
  469.  
  470.  
  471.     .type    _init_stk,@object
  472.     .size    _init_stk,4
  473.     .bss    _init_stk,4
  474.  
  475.     .type    _startup_data,@object
  476.     .size    _startup_data,4
  477.     .bss    _startup_data,4
  478.  
  479.     .type    _argv,@object
  480.     .size    _argv,4
  481.     .bss    _argv,4
  482.  
  483.     .global    _stdin
  484.     .type    _stdin,@object
  485.     .size    _stdin,4
  486.     .comm    _stdin,4
  487.  
  488.     .global    _stdout
  489.     .type    _stdout,@object
  490.     .size    _stdout,4
  491.     .comm    _stdout,4
  492.  
  493.     .global    _stderr
  494.     .type    _stderr,@object
  495.     .size    _stderr,4
  496.     .comm    _stderr,4
  497.  
  498.     .global    SysBase
  499.     .type    SysBase,@object
  500.     .size    SysBase,4
  501.     .comm    SysBase,4
  502.  
  503. .if    DEBUG
  504.     .bss    .regsave,11*4        # r0,r3,...,r12
  505.     .bss    .datastream,4*4        # max. 4 arguments
  506. .endif
  507.